package technicalservices.database;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;

import application.config.Config;
import domain.advertisement.Ad;
import domain.advertisement.AdvertisementScheme;
import domain.tournament.ITournament;
import domain.users.User;

public class PersistanseStorage {

	private static PersistanseStorage instance;
	private Database database;
	private final String USER_TABLE = "Arena_User_Table";
	private final String ADVERTISEMENT = "Arena_Ads_Table";

	private PersistanseStorage() {
		database = new MsSQL();
		database.connect(Config.DB_HOST, Config.DB_USER, Config.DB_PASSWORD,
				Config.DB_DATABASE, Config.DB_PORT);
	}

	public static PersistanseStorage getInstance() {
		if (instance == null) {
			instance = new PersistanseStorage();
		}

		return instance;
	}

	/** Installs the database tables */
	private void createTables() {
		System.out.println("Creating tables");
	}

	/** Saves a user to the database */
	public boolean saveUser(String name, String email, String password,
			String type) {
		String saveUser = "INSERT INTO " + USER_TABLE
				+ "(User_email, User_Password, User_Name, User_type) VALUES ('"
				+ email + "', '" + password + "', '" + name + "', '" + type
				+ "')";
		try {
			database.executeUpdate(saveUser);
		} catch (SQLException ex) {
			System.out.println("DatabaseHandler.saveUser() -> SQLException: "
					+ ex);
			return false;
		}
		return true;
	}

	public String[] getUser(String email) {
		database.executeSQL("Select * FROM " + USER_TABLE
				+ " WHERE User_email = '" + email + "';");
		ResultSet rs = database.getResultSet();
		String[] user = new String[5];
		try {
			while (rs.next()) {
				user[0] = String.valueOf(rs.getInt("User_Id"));
				user[1] = rs.getString("User_email");
				user[2] = rs.getString("User_Password");
				user[3] = rs.getString("User_Name");
				user[4] = rs.getString("User_type");
				return user;
			}
		} catch (SQLException ex) {
			System.out.println("SQLException in getUser: " + ex);
		}
		return null;
	}

	/*
	 * This method returns the unique userId
	 * 
	 * @param email The unique email adress that have a matching user ID.
	 * 
	 * @return userId
	 */
	public int retrieveUserId(String email) {
		String userId = "SELECT User_Id FROM " + USER_TABLE
				+ " WHERE User_email = '" + email + "';";
		int user = 0;
		database.executeSQL(userId);
		ResultSet rs = database.getResultSet();
		try {
			while (rs.next()) {
				user = Integer.parseInt(rs.getString("User_Id"));
			}
		} catch (SQLException ex) {
			System.out.println("SQLException" + ex);
		}
		return user;
	}

	/*
	 * This method is to check if the password is matching.
	 * 
	 * @param email The unique email adress.
	 * 
	 * @param password The password that the user enters.
	 * 
	 * @return boolean TRUE if the password is a match else FALSE
	 */

	public boolean checkPassword(String email, String password) {
		try {
			String userId = "SELECT User_Password FROM " + USER_TABLE
					+ " WHERE User_Email = '" + email
					+ "' AND User_password = '" + password + "';";
			database.executeSQL(userId);
			ResultSet rs = database.getResultSet();
			return rs.next();
		} catch (SQLException ex) {
			return false;
		}
	}

	/*
	 * This method is to check if the email already exists in the database.
	 * 
	 * @param email The unique email adress.
	 * 
	 * @return boolean TRUE if the email exists else FALSE
	 */
	public boolean emailExists(String email) {
		database.executeSQL("SELECT * FROM " + USER_TABLE
				+ " WHERE User_email = '" + email + "';");
		try {
			if (database.getResultSet().next()) {
				return true;
			}
		} catch (SQLException ex) {
			System.out.println("SQLException" + ex);
		}
		return false;
	}

	/*
	 * This method is to check if the username already exists in the database.
	 * 
	 * @param username The username.
	 * 
	 * @return boolean TRUE if the username exists else FALSE
	 */
	public boolean usernameExists(String username) {
		database.executeSQL("SELECT User_Name FROM " + USER_TABLE
				+ " WHERE User_name = '" + username + "';");
		ResultSet rs = database.getResultSet();
		String user = "";
		try {
			while (rs.next()) {
				user = rs.getString("User_Name");
			}
		} catch (SQLException ex) {

		}
		if (user == "") {
			return false;
		}
		return true;
	}

	public void saveAdvertisement(int advertiserID, ImageIcon image,
			String descrition, AdvertisementScheme advertisemenetScheme,
			boolean approval) {
	}

	public void setAdvertisement(int advertiserID, Ad ad) {
		PreparedStatement prstm = null;
		try {
			prstm = database.getConnection().prepareStatement(
					"INSERT INTO ? (Advertiser_Id, Advert) VALUES (?, ?)");

			prstm.setString(1, "Arena_Ads");
			prstm.setInt(2, advertiserID);
			prstm.setBytes(3, setObject(ad));
			prstm.executeUpdate();
			// return true;
		} catch (SQLException e) {
			System.out.println("SQLException in SetAD: " + e);
			e.printStackTrace();
			// return false;
		}

	}

	private Object getObject(byte[] bajt) {
		ByteArrayInputStream bais = new ByteArrayInputStream(bajt);
		ObjectInput oi;
		Object o = null;
		try {
			oi = new ObjectInputStream(bais);
			o = oi.readObject();
			bais.close();
			oi.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return o;
	}

	private byte[] setObject(Object o) {
		ByteArrayOutputStream bos = null;
		ObjectOutput out = null;
		byte[] bytes = null;
		try {
			bos = new ByteArrayOutputStream();
			out = new ObjectOutputStream(bos);
			out.writeObject(o);
			bytes = bos.toByteArray();
			out.close();
			bos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return bytes;
	}

	public List<User> getUsers(String userType) {
		database.executeSQL("Select * FROM " + USER_TABLE
				+ " WHERE User_type = '" + userType + "';");
		ResultSet rs = database.getResultSet();
		String[] user = new String[5];
		List<User> advertisers = new ArrayList<User>();
		try {
			while (rs.next()) {
				advertisers.add(new User(rs.getInt("User_Id"), rs
						.getString("User_Name"), rs.getString("User_email"), rs
						.getString("User_type")));
			}
		} catch (SQLException ex) {
			System.out.println("SQLException in getUser: " + ex);
		}
		return advertisers;
	}

	public void archiveTournament(ITournament remove) {
		FileHandler fh = new FileHandler("ArchivedTournaments.dat");
		List<ITournament> archived = (List<ITournament>) fh.loadFile();
		archived.add(remove);
		fh.saveFile(archived);
	}

	public void saveGame(String gameURL) {
		// TODO Auto-generated method stub
	}

	public List<Ad> getAds() {
		return (List<Ad>) new FileHandler("AdDatabase.dat").loadFile();
	}

	public void saveAds(List<Ad> ads) {
		new FileHandler("AdDatabase.dat").saveFile(ads);
	}

	public List<ITournament> getTournaments() {
		return (List<ITournament>)new FileHandler("Tournaments.dat").loadFile();
	}

	public void saveTournaments(List<ITournament> tournaments) {
		new FileHandler("Tournaments.dat").saveFile(tournaments);
	}

}
